package cn.demomaster.quicklogger.format;

import static android.content.ContentValues.TAG;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import org.jetbrains.annotations.NotNull;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

import cn.demomaster.qdlogger.BuildConfig;
import cn.demomaster.quicklogger.LogLevel;
import cn.demomaster.quicklogger.config.LogConfig;
import cn.demomaster.quicklogger.model.LogInfo;
import cn.demomaster.quicklogger.util.FileUtil;
import kotlin.Pair;

public class LogFormat {

    private static final char TOP_LEFT_CORNER = '┌';
    private static final char BOTTOM_LEFT_CORNER = '└';
    private static final char MIDDLE_CORNER = '├';
    private static final char HORIZONTAL_LINE = '│';
    private static final char HORIZONTAL_LINE2 = '║';
    private static final String DOUBLE_DIVIDER_CELL = "─";
    private static final String END = "\n";
    private static final String HORIZONTAL_LINE_END = "│\n";
    private static final String DOUBLE_DIVIDER = "────────────────────────────────────────────────────────";

    static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.CHINA);
    public static SimpleDateFormat simpleTimeFormat = new SimpleDateFormat("HH:mm:ss:SSS", Locale.CHINA);

    public LogFormat() {
    }

    public LogFormat(SimpleDateFormat simpleDateFormat) {
        // this.simpleDateFormat = simpleDateFormat;SimpleDateFormat("HH:mm:ss:SSS", Locale.CHINA)
    }
    public String formatHeader(String formatStr, LogInfo logEntry) {
        return formatHeader(formatStr, logEntry.getTag(), logEntry.getFileName(), logEntry.getLineNumber(), logEntry.getLevel(), logEntry.getThreadId());
    }

    public String formatHeader(String formatStr, String tag, String clazzFileName, int lineNum, LogLevel level, long threadId) {
        StringBuilder sb = new StringBuilder(formatStr);
        if (sb.indexOf("time") >= 0) {
            sb.replace(sb.indexOf("time"), sb.indexOf("time") + "time".length(), simpleTimeFormat.format(new Date()));
        }
        if (sb.indexOf("tag") >= 0) {
            sb.replace(sb.indexOf("tag"), sb.indexOf("tag") + "tag".length(), tag);
        }
        if (sb.indexOf("class") >= 0) {
            sb.replace(sb.indexOf("class"), sb.indexOf("class") + "class".length(), clazzFileName + ":" + lineNum);
        }
        if (sb.indexOf("level") >= 0) {
            sb.replace(sb.indexOf("level"), sb.indexOf("level") + "level".length(), level.name().substring(0, 1));
        }
        if (sb.indexOf("thread") >= 0) {
            sb.replace(sb.indexOf("thread"), sb.indexOf("thread") + "thread".length(), "[" + threadId + "]");
        }

        return sb.toString();
    }

    static MapKeyComparator mapKeyComparator;

    /**
     * 使用 Map按key进行排序
     *
     * @param map
     * @return
     */
    public static Map<Integer, String> sortMapByKey(Map<Integer, String> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        if (mapKeyComparator == null) {
            mapKeyComparator = new MapKeyComparator();
        }
        Map<Integer, String> sortMap = new TreeMap<>(mapKeyComparator);
        sortMap.putAll(map);
        return sortMap;
    }

    public String formatEnd(String str) {
        if (!str.trim().endsWith("\n") && !str.trim().endsWith("\n\r")) {
            return str + "\n";
        }
        return str;
    }

    /**
     * 获取simpleName
     *
     * @param str
     * @return
     */
    private static String getClazzSimpleName(String str) {
        if (TextUtils.isEmpty(str)) {
            return "";
        }
        String[] arr = str.split("\\u002E");
        if (arr.length >= 1) {
            return arr[arr.length - 1];
        }
        return str;
    }

    private static final String LOG_HEADER_FORMAT = "\rALog V1.0.12\n\r" +
            "日期：%s\n\r" +
            "包名：%s\n\r" +
            "版本名称：%s\n\r" +
            "版本号：%s";

    public static String formatFileHeaderWithGraphic(Context mContext) {
        String date = simpleDateFormat.format(new Date());
        String packageName = mContext.getPackageName();
        String versionName = FileUtil.getVersionName(mContext);
        String versionCode = String.valueOf(FileUtil.getVersionCode(mContext));
        return formatWithGraphic(String.format(LOG_HEADER_FORMAT, date, packageName, versionName, versionCode));
    }

    public static String formatWithGraphic(String content) {
        if (content == null || content.trim().isEmpty()) {
            return ""; // 或者返回一个默认的空框，根据您的需求
        }
        // 使用正则表达式分割字符串
        String[] lines = content.split("\\R");//正则表达式优化：split("\\r?\\n") 是一个很常见的换行符匹配，但可以简化为 split("\\R")。\\R 是一个匹配任何类型换行符的通用正则表达式（在 Java 7 及以上版本支持）。

        // 找出最长的一行，用于确定边框宽度
        int maxLength = 0;
        for (String line : lines) {
            int lineLength = line.trim().length();
            if (lineLength > maxLength) {
                maxLength = lineLength;
            }
        }
        // 生成对应长度的分隔线
        StringBuilder dividerBuilder = new StringBuilder();
        for (int i = 0; i < maxLength; i++) {
            dividerBuilder.append("─"); // 使用短横线，您可以根据需要替换为其他字符
        }

        String DIVIDER_LINE = dividerBuilder.toString();
        StringBuilder stringBuilder = new StringBuilder();
        String topLine = "┌" + DIVIDER_LINE + "\n";
        stringBuilder.append(topLine);
        // 打印分割后的每一行
        for (String line : lines) {
            if (!line.trim().isEmpty()) { // 只处理非空行
                stringBuilder.append("│ ").append(line.trim()).append("\n");
            }
        }

        String line2 = "└" + DIVIDER_LINE + "\n";//String.format("└%-10" + "s┘\t\t\t\t\n", DOUBLE_DIVIDER);
        stringBuilder.append(line2);
        return stringBuilder.toString();
    }

    @NotNull
    public String getHeaderStr(@NotNull LogInfo logEntry) {
        String logMessage = String.format(
                "(%s:%d): %s",
                logEntry.getFileName(),
                logEntry.getLineNumber(),
                logEntry.getMsg()
        );
        return logMessage;
    }


    /**

     * 格式化日志头和正文

     */

    public Pair<String, String> formatLogContent(LogConfig mConfig,LogInfo logInfo, LogInfo previousLogInfo) {
        String header = null;
        String body = null;
        if (mConfig.getUsingGraphics()) {
            header = formatHeader(mConfig.getLineHeaderFormat(), logInfo);
            body = String.valueOf(logInfo.getMsg());
            // 处理重复日志

            if (previousLogInfo != null && logInfo.getMsg().equals(previousLogInfo.getMsg())) {
                body = "|";
                if (logInfo.getLevel() == previousLogInfo.getLevel()
                        && logInfo.getTag().equals(previousLogInfo.getTag())
                        && logInfo.getFileName().equals(previousLogInfo.getFileName())
                        && logInfo.getMethodName().equals(previousLogInfo.getMethodName())
                        && logInfo.getLineNumber() == previousLogInfo.getLineNumber()) {
                    header = LogFormat.simpleTimeFormat.format(new Date()) + " ";
                }
            }
        }
        return new Pair<>(header != null ? header : "", body != null ? body : "");
    }

    @NotNull
    public static String formatContent(Object obj) {
        if (obj == null) {
            return "null";
        } else if (obj instanceof String) {
            return (String) obj;
        } else if (obj instanceof Throwable) {
            return Log.getStackTraceString((Throwable) obj);
        } else if (obj instanceof List) {
            return formatList((List<?>) obj);
        } else if (obj.getClass().isArray()) {
            // 如果 obj 是一个数组，使用 Arrays.toString() 来格式化
            if (obj instanceof int[]) {
                return Arrays.toString((int[]) obj);
            } else if (obj instanceof long[]) {
                return Arrays.toString((long[]) obj);
            } else if (obj instanceof double[]) {
                return Arrays.toString((double[]) obj);
            } else if (obj instanceof float[]) {
                return Arrays.toString((float[]) obj);
            } else if (obj instanceof boolean[]) {
                return Arrays.toString((boolean[]) obj);
            } else if (obj instanceof byte[]) {
                return Arrays.toString((byte[]) obj);
            } else if (obj instanceof char[]) {
                return Arrays.toString((char[]) obj);
            } else if (obj instanceof short[]) {
                return Arrays.toString((short[]) obj);
            } else {
                // 对象数组
                return Arrays.toString((Object[]) obj);
            }
        }
        return obj.toString();
    }

    private static String formatList(List<?> list) {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < list.size(); i++) {
            if (i > 0) {
                sb.append(", ");
            }
            sb.append(formatContent(list.get(i)));
        }
        sb.append("]");
        return sb.toString();
    }
}
